package game.sprite.collision;

import java.awt.geom.PathIterator;
import java.util.ArrayList;
import java.util.List;


/**
 * A simple implementation of a CollisionManager. Iterates through
 * every possible combination of ICollidables and checks whether
 * a collision has occurred between the two. If one of these collisions
 * occurs, simulation of these collisions is delegated to the accept()
 * method of each ICollidable.
 * 
 * @author Paul
 * 
 */
public class SimpleCollisionManager implements ICollisionManager {

    private List<ICollidable> myCollidables;

    /**
     * Creates a SimpleCollisionManager that currently does not
     * oversee the collisions of any objects.
     */
    public SimpleCollisionManager() {
        myCollidables = new ArrayList<ICollidable>();
    }

    /**
     * Creates a SimpleCollisionManager that is capable of simulating
     * the collisions of the objects contained in the argument.
     * 
     * @param collidablesToSimulate A List containing the objects that
     *        this SimpleCollisionManager will simulate the collisions for.
     */
    public SimpleCollisionManager(List<ICollidable> collidablesToSimulate) {
        myCollidables = collidablesToSimulate;
    }

    /**
     * Will register an object with the SimpleCollisionManager. This object's
     * collisions will now be simulated when a call is made to simulate().
     * 
     * @param collidable The collidable that will now have its collisions
     *        simulated by this SimpleCollisionManager.
     */
    @Override
    public void add(ICollidable collidable) {
        if (collidable != null) {
            myCollidables.add(collidable);
        }
    }

    @Override
    public void remove(ICollidable toRemove) {
        myCollidables.remove(toRemove);
    }

    /**
     * An algorithmically inefficient implementation of collision
     * simulations between a group of objects.
     */
    @Override
    public void update() {
        for (ICollidable firstCollidable : myCollidables) {
            for (int i = 0; i < myCollidables.size(); i++) {
                ICollidable secondCollidable = myCollidables.get(i);
                if (!firstCollidable.equals(secondCollidable) &&

                    isIntersecting(firstCollidable, secondCollidable)) {
                       
     
                    firstCollidable.accept(secondCollidable);

                }
            }
        }
    }

    /**
     * Checks to see if two collidable objects intersect by testing each point
     * in the outline of the first collidable and seeing if it is inside the
     * outline of the second collidable.
     * 
     * @param first
     * @param second
     * @return true if of of the points that make up the first collidable lies
     *         within the second collidable.
     */
    private boolean isIntersecting(ICollidable first, ICollidable second) {
        PathIterator outlineIterator = first.getOutline().getPathIterator(null);
        while (!outlineIterator.isDone()) {
            double[] coords = new double[2];
            outlineIterator.currentSegment(coords);
            if (second.getOutline().contains(coords[0], coords[1])) { return true; }
            outlineIterator.next();
        }
        return false;
    }

}
